#include "Scene.h"
#include "Sphere.h"
#include <cmath>

using namespace std;

Scene::Scene(void)
{
	resX = resY = 100;
	fovX = 45;
	fovY = 45;
	eye = Point(0,0,0);
	gaze = Vec3f(0,0, -1);
	up = Vec3f(0, 1, 0);
	focal = 1.0f;

	surfaces.push_back(new Sphere());
	Sphere *s = new Sphere();
	s->center = Point(0,0, -3);
	s->radius = 1;
	s->color = Pixel(0.0f, 1.0f, 0.0f);
	surfaces.push_back(s);
	
}


Scene::~Scene(void)
{
}

bool Scene::Hit(Point eye, Vec3f dir, HitRecord *hit)
{
	vector<Surface*>::iterator i;
	bool got_hit = false;
	for (i = surfaces.begin(); i != surfaces.end(); i++)
	{
		if ((*i)->Hit(eye, dir, hit))
			got_hit = true;
	}
	return got_hit;
}


Image* Scene::Render()
{
	//first create the image object that we'll fill in
	Image* outImage = new Image(resX, resY);
	
	//now we have to create the view plane that we'll
	//find the top left point for the view plane
	Point center = eye + focal*gaze;
	Vec3f right = crossProduct(gaze, up);
	right.normalize();
	float howmuchright = tanf(fovX/2) * focal;
	Vec3f realUp = crossProduct(right, gaze);
	realUp.normalize();
	float howmuchup = tanf(fovY/2) * focal;

	Point topleft = center + howmuchup*realUp - howmuchright * right;
	Vec3f deltaX = (howmuchright*2)/resX * right;
	Vec3f deltaY = -1*(howmuchup*2)/resY * realUp;
	HitRecord hit;
	int i,j;
	for(j = 0; j < resY; j++)
	{
		for (i = 0; i < resX; i++)
		{
			hit.t = 10000.0f;
			if (Hit(eye, (topleft + (float)i*deltaX + (float)j*deltaY) - eye, &hit))
			{
				(*outImage)(i,j) = hit.surface->Shade(hit.location, Vec3f());
			}
			else
			{
				(*outImage)(i,j) = Pixel(0,0,0);
			}	
		}
	}
	return outImage;
}
